package com.sleet.yuemiao.service.impl;

import com.sleet.yuemiao.comment.YuMiaoComment;
import com.sleet.yuemiao.even.DemoEvent;
import com.sleet.yuemiao.pojo.CustInfo;
import com.sleet.yuemiao.service.YueMiaoService;
import com.sleet.yuemiao.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicHeader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: yuemiao
 * @ClassName YueMiaoService
 * @description:
 * @author: Liyongxing
 * @create: 2021-12-23 09:25
 **/
@Slf4j
@Service
@EnableConfigurationProperties({CustInfo.class})
public class YueMiaoServiceImpl implements YueMiaoService {

    @Value("${even.zftsl}")
    String zftsl;
    @Value("${even.Cookie}")
    String cookie;
    @Value("${even.iv}")
    String iv;
    @Value("${even.signature}")
    String key;
    @Value("${even.setCookie}")
    String setCookie;

    @Autowired
    CustInfo custInfo;
    Map<String,String> parm = new HashMap<>();
    @Resource
    YuMiaoComment yuMiaoComment;
//    List<CustInfo> custInfos = new LinkedList<>();
    @Autowired
    private ApplicationContext applicationContext;

    /**
     * 点击某一个具体的医院时 根据id 选择具体的医院
     *      * @return 可以预约九价的疫苗列表
     * @param id 医院id
     * @param lat 经纬度
     * @param lng
     * @param
     * @return 返回疫苗列表
     */
    @Override
    public Object selectValidTimeByCid(String id,String lat,String lng){
        //判断当前医院 是否已经成功加载了可以预约的疫苗
        if(yuMiaoComment.getComment().get(id) == null){
            String url = "https://cloud.cn2030.com/sc/wx/HandlerSubscribe.ashx?act=CustomerProduct&id=%s&lat=%s&lng=%s";
            String fUrl = String.format(url, id, lat, lng);
            String   response = null;
            
            try {
                log.info("发起获取医院疫苗接口【{}】",id);
                response = HttpUtil.request(null, fUrl,
                        HttpUtil.METHOD_POST,
                        parm, HttpUtil.PARAM_TYPE_JSON, getCommonHeader(null).toArray(new BasicHeader[0]), null
                );

            } catch (Exception e) {
                e.printStackTrace();
            }
            Map<Object, Object> objectObjectMap = JsonUtil.toMap(new String(response));
            log.info("获取医院疫苗接口响应结果【{}】,{}",id,objectObjectMap);
            //疫苗列表
            Object list = objectObjectMap.get("list");
            if(list != null){
                //获得疫苗列表
                List<Map<String, Object>> list1 = JsonUtil.toList(list);
                List<Map<String, Object>> valids = list1.stream().filter(item -> {
                    //插入医院id 备用
                    item.put("cid",id);
                    //TODO  换位 九价
//            return "立即预约".equals(item.get("BtnLable").toString()) && "九价人乳头瘤病毒疫苗".equals(item.get("text").toString());
//            return "立即预约".equals(item.get("BtnLable").toString()) && (item.get("text").toString().contains("九价"));
                    return "立即预约".equals(item.get("BtnLable").toString());
                }).collect(Collectors.toList());
                //疫苗可预约的时间列表获取
                List<Map<String, Object>> validTime = this.getValidTime(valids);
                if(!CollectionUtils.isEmpty(validTime)){
                    yuMiaoComment.getComment().put(id,validTime);
                    //根据时间获取 密文
                    GetCustSubscribeDateDetail();
                }
            }
        }
        // 等于0 说明获取密文是请求 全部超时 再次请求
        else if(yuMiaoComment.getComment().size() == 0){
            //根据时间获取 密文
            GetCustSubscribeDateDetail();
        }
        return yuMiaoComment.getComment();
    }
    /**
     * 获取疫苗的可以预约的有效时间
     * @param selectValidTimeByCids
     */
    private List<Map<String, Object>> getValidTime(List<Map<String, Object>> selectValidTimeByCids) {
        //202112
        String month = DateFormatUtils.format(new Date(), "yyyyMM");
        List<Map<String, Object>> validTimes = new ArrayList<>();
        if(!CollectionUtils.isEmpty(selectValidTimeByCids)){
            //根据疫苗获取可预约的时间
            for (Map<String, Object> valid:selectValidTimeByCids){
                String  pid = valid.get("id").toString();
                String  id = valid.get("cid").toString();
                try {
                    Thread.sleep(1500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                String validTimeUrl = "https://cloud.cn2030.com/sc/wx/HandlerSubscribe.ashx?act=GetCustSubscribeDateAll&pid="+pid+"&id="+id+"&month="+month;
                String validTimeReponse = null;
                try {
                    log.info("发起疫苗可约时间接口疫苗id【{}】，医院id【{}】",pid,id);
                    validTimeReponse = HttpUtil.request(null,validTimeUrl,
                            HttpUtil.METHOD_POST,
                            parm, HttpUtil.PARAM_TYPE_JSON,getCommonHeader(null).toArray(new BasicHeader[0]),null
                    );
                } catch (Exception e) {
                }
                Map<Object, Object> response = JsonUtil.toMap(validTimeReponse);
                log.info("疫苗id【{}】,医院id【{}】疫苗可约时间接口疫苗响应，{}",pid,id,validTimeReponse);
                Object validTimeObj = response.get("list");
                validTimes = JsonUtil.toList(validTimeObj)
                        .stream().map(obj ->{
                            obj.put("cname",valid.get("cname"));
                            obj.put("text",valid.get("text"));
                            obj.put("id",id);
                            obj.put("pid",pid);
                            return obj;
                        }).collect(Collectors.toList());
            }
        }
        if(!CollectionUtils.isEmpty(validTimes)){
            validTimes = validTimes.stream().filter(obj -> {
                return "true".equals(obj.get("enable").toString());
            }).collect(Collectors.toList());
        }
        return validTimes;
    }

    /**
     * 根据医院可以预约的时间 活的疫苗数
     * @return
     */
    @Override
    public String GetCustSubscribeDateDetail() {
        String singnature = key.substring(0, 16);
        String response = "";
        Map<String, Object> validTime = yuMiaoComment.getComment();
        if(validTime.size() > 0){
            for(String id :validTime.keySet()){
                List<Map<String, Object>> validTimes = (List<Map<String, Object>>) validTime.get(id);
                if(!CollectionUtils.isEmpty(validTimes)){
                    //TODO  加入线程线程
//                    {"date":"2021-12-24","enable":true,"cname":null,"pid":"64","text":"重组带状疱疹疫苗（CHO细胞）","id":"1885"}
                    for (Map<String, Object> time:validTimes){
                        String url = "https://cloud.cn2030.com/sc/wx/HandlerSubscribe.ashx?act=GetCustSubscribeDateDetail" +
                                "&pid=%s" +
                                "&id=%s" +
                                "&scdate=%s";
                        String fUrl = String.format(url, time.get("pid").toString(), time.get("id").toString().trim(), time.get("date").toString());
                        try {
                            Thread.sleep(1000);
                            log.info("根据可约时间获取加密数据获得mxid，id【{}】，医院id【{}】当前预约的时间{}",time.get("pid"),id,time.get("date"));
                            String responseHex = HttpUtil.request(null,fUrl,
                                    HttpUtil.METHOD_POST,
                                    parm, HttpUtil.PARAM_TYPE_JSON,getCommonHeader(null).toArray(new BasicHeader[0]),null
                            );
                            Thread.sleep(1000);
                            log.info("根据可约时间获取加密数据获得mxid接口疫苗响应，pid={},id={},res={}",time.get("pid"),id,responseHex);
                            String bas = Base64Utils.encodeToString(HexString.hexStr2Str(responseHex));
                            String plaintext = AESUtil.decryptString(Base64Utils.decode(bas.getBytes()),singnature,iv);
                            log.info("根据可约时间获取加密数据获得mxid接口疫苗响应，解密数据,pid={},id={},明文【{}】",time.get("pid"),id,plaintext);
                            Map<String, Object> objectObjectMap = JsonUtil.toMap(plaintext);
                            Object list = objectObjectMap.get("list");
                            List<Map<String, Object>> list1 = JsonUtil.toList(list);
                            if(!CollectionUtils.isEmpty(list1)){
                                Map<String, Object> map = list1.get(0);
                                String mxid =(String) map.get("mxid");
                                String pid =(String)time.get("pid");
                                String date =(String)time.get("date");
                                custInfo.setMxid(mxid);
                                custInfo.setPid(pid);
                                custInfo.setDate(date);
                                log.info("可以发起直接预约的对象数据{}",custInfo);
                                //发送事件
                                applicationContext.publishEvent(new DemoEvent(custInfo, " date "+custInfo.getDate()
                                        +" Mxid "+custInfo.getMxid()+" pid "+custInfo.getPid()));
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }

            }
        }
        return response;
    }

    @Override
    public CustInfo getCaptcha(CustInfo custInfo){
        HttpResponse response = null;
        try {
            Thread.sleep(1000);
            String url = "https://cloud.cn2030.com/sc/wx/HandlerSubscribe.ashx?act=GetCaptcha&mxid="+custInfo.getMxid();
            HttpClient client = HttpClientBuilder.create().build();
            log.info("发起预约之前的一步校验获得新的cookie【URL：{}】",url);
            HttpPost request = new HttpPost(url);
            RequestConfig globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.DEFAULT).build();
            RequestConfig localConfig = RequestConfig.copy(globalConfig).setCookieSpec(CookieSpecs.STANDARD_STRICT)
                    .build();
            request.setConfig(localConfig);
            request.setHeaders(getCommonHeader(null).toArray(new BasicHeader[0]));

            response = client.execute(request);
            log.info("发起预约之前的一步校验获得新的cookie;响应结果【{}】",response);
        } catch (Exception e) {
            e.printStackTrace();
        }

        Header[] headers = response.getAllHeaders();
        for (Header header : headers) {
            if(setCookie.equals(header.getName())){
                custInfo.setCookie(header.getValue());
            }
        }
        return custInfo;
    }

    @Override
    public Object Save20(CustInfo custInfo){
        String birthday= custInfo.getBirthday();
        String tel= custInfo.getTel();
        String sex =  custInfo.getSex();
        String cname = custInfo.getCname();
        String idcard = custInfo.getIdcard();
        String mxid= custInfo.getMxid();
        String date= custInfo.getDate();
        String pid= custInfo.getPid();

        String curl = "https://cloud.cn2030.com/sc/wx/HandlerSubscribe.ashx?act=Save20" +
                "&birthday=%s" +
                "&tel=%s" +
                "&sex=%s" +
                "&cname=%s" +
                "&doctype=1" +
                "&idcard=%s" +
                "&mxid=%s" +
                "&date=%s" +
                "&pid=%s" +
                "&Ftime=1&guid=";
        curl = String.format(curl,birthday,tel,sex,cname,idcard,mxid,date,pid);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String response = HttpUtil.request(null,curl,
                HttpUtil.METHOD_POST,
                parm, HttpUtil.PARAM_TYPE_JSON,getCommonHeader(custInfo.getCookie()).toArray(new BasicHeader[0]),null
        );
        log.info("预约结果"+response+"时间"+custInfo.getDate());
        return response;
    }



    /**
     * 生成header
     * @return
     */
    private List<Header> getCommonHeader(String newCookie){
        List<Header> headers = new ArrayList<>();
        headers.add(new BasicHeader("Host","cloud.cn2030.com"));
        headers.add(new BasicHeader("Connection", "keep-alive"));
        if(StringUtils.isEmpty(newCookie)){
            headers.add(new BasicHeader("Cookie", cookie));
        }else {
            headers.add(new BasicHeader("Cookie", newCookie));
        }
        headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat"));
        headers.add(new BasicHeader("content-type", "application/json"));
        /**       headers.add(new BasicHeader("zftsl", zftsl));*/
        headers.add(new BasicHeader("zftsl", UUID.randomUUID().toString().replace("-","")));
        headers.add(new BasicHeader("Accept-Encoding","gzip, deflate, br"));
        return headers;
    }
}
